import logging
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db import transaction
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.authentication import TokenAuthentication
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from api_test.common.api_response import JsonResponse
from api_test.common.common import record_dynamic
from api_test.models import Project, GlobalHost
from api_test.serializers import GlobalHostSerializer, ProjectListSerializer

logger = logging.getLogger(__name__)  # 这里使用 __name__ 动态搜索定义的 logger 配置，这里有一个层次关系的知识点。


class HostTotal(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="name", in_=openapi.IN_QUERY, type=openapi.TYPE_STRING, description="host名称"),
        openapi.Parameter(name="page", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="当前页数"),
        openapi.Parameter(name="page_size", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER,
                          description="每页最多显示的host数"),
    ])
    def get(self, request):
        """
        获取host列表
        """
        try:
            page_size = int(request.GET.get("page_size", 1000))
            page = int(request.GET.get("page", 1))
        except (TypeError, ValueError):
            return JsonResponse(code="999995", msg="page and page_size must be integer！")
        project_id = request.GET.get("project_id")
        if not project_id.isdecimal():
            return JsonResponse(code="999995", msg="参数有误！")
        try:
            pro_data = Project.objects.get(id=project_id)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在！")
        pro_data = ProjectListSerializer(pro_data)
        if not pro_data.data["status"]:
            return JsonResponse(code="999985", msg="该项目已禁用")
        name = request.GET.get("name")
        obi = GlobalHost.objects.filter(project=project_id, status=True)
        if name:
            obi = obi.filter(name__contains=name)
        obi = obi.order_by("id")

        paginator = Paginator(obi, page_size)  # paginator对象
        total = paginator.num_pages  # 总页数
        try:
            obm = paginator.page(page)
        except PageNotAnInteger:
            obm = paginator.page(1)
        except EmptyPage:
            obm = paginator.page(paginator.num_pages)
        serialize = GlobalHostSerializer(obm, many=True)
        return JsonResponse(data={"data": serialize.data,
                                  "page": page,
                                  "total": total
                                  }, code="999999", msg="成功！")


class AddHost(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 必传参数 name, host
            if not data.get("project_id") or not data.get("name") or not data.get("host"):
                return JsonResponse(code="999995", msg="参数有误！")
            # 校验project_id类型为int
            if not isinstance(data["project_id"], int):
                return JsonResponse(code="999995", msg="参数有误！")
            if "port" in data:  # 针对doc调试时的处理
                port = data["port"]
                if port == 0:
                    data.pop("port")
        except KeyError:
            return JsonResponse(code="999995", msg="参数有误！")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'name', 'host', 'port'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="host名称"),
            'host': openapi.Schema(type=openapi.TYPE_STRING, description="host IP"),
            'port': openapi.Schema(type=openapi.TYPE_INTEGER, description="host port"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="host描述")
        },
    ))
    def post(self, request):
        """
        新增Host
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            obj = Project.objects.get(id=data["project_id"])
            if not request.user.is_superuser and obj.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在！")
        pro_data = ProjectListSerializer(obj)
        if not pro_data.data["status"]:
            return JsonResponse(code="999985", msg="该项目已禁用")
        obi = GlobalHost.objects.filter(name=data["name"], project=data["project_id"])
        if obi:
            return JsonResponse(code="999997", msg="存在相同名称！")
        else:
            serializer = GlobalHostSerializer(data=data)
            with transaction.atomic():
                if serializer.is_valid():
                    # 外键project_id
                    serializer.save(project=obj)
                    # 记录动态
                    record_dynamic(project=data["project_id"],
                                   _type="添加", operationObject="域名", user=request.user.pk,
                                   data="新增域名“%s”" % data["name"])
                    return JsonResponse(data={
                        "host_id": serializer.data.get("id")
                    }, code="999999", msg="成功！")
                return JsonResponse(code="999998", msg="失败！")


class UpdateHost(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 必传参数 name, host
            if not data.get("name") or not data.get("host") or not data.get("project_id") or not data.get("id"):
                return JsonResponse(code="999995", msg="参数有误！")
            # 校验project_id类型为int
            if not isinstance(data["project_id"], int) or not isinstance(data["id"], int):
                return JsonResponse(code="999995", msg="参数有误！")
        except KeyError:
            return JsonResponse(code="999995", msg="参数有误！")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['id', 'project_id', 'name', 'host', 'port'],
        properties={
            'id': openapi.Schema(type=openapi.TYPE_INTEGER, description="host id"),
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="host名称"),
            'host': openapi.Schema(type=openapi.TYPE_STRING, description="host IP"),
            'port': openapi.Schema(type=openapi.TYPE_INTEGER, description="host port"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="host描述")
        },
    ))
    def post(self, request):
        """
        修改host域名
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"])
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在！")
        pro_data = ProjectListSerializer(pro_data)
        if not pro_data.data["status"]:
            return JsonResponse(code="999985", msg="该项目已禁用")
        try:
            obi = GlobalHost.objects.get(id=data["id"])
        except ObjectDoesNotExist:
            return JsonResponse(code="999992", msg="host不存在！")
        host_name = GlobalHost.objects.filter(name=data["name"]).exclude(id=data["id"])
        if len(host_name):
            return JsonResponse(code="999997", msg="存在相同名称！")
        else:
            serializer = GlobalHostSerializer(data=data)
            with transaction.atomic():
                if serializer.is_valid():
                    # 外键project_id
                    serializer.update(instance=obi, validated_data=data)
                    # 记录动态
                    record_dynamic(project=data["project_id"],
                                   _type="修改", operationObject="域名", user=request.user.pk,
                                   data="修改域名“%s”" % data["name"])
                    return JsonResponse(code="999999", msg="成功！")
                else:
                    print(serializer.errors)
                return JsonResponse(code="999998", msg="失败！")


class DelHost(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验project_id类型为int
            if not isinstance(data["ids"], list) or not isinstance(data["project_id"], int):
                for i in data["ids"]:
                    if not isinstance(i, int) or not isinstance(int(i), int):
                        return JsonResponse(code="999995", msg="参数有误！")
                return JsonResponse(code="999995", msg="参数有误！")
        except KeyError:
            return JsonResponse(code="999995", msg="参数有误！")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'ids'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_INTEGER),
                                  description="待删除待host id列表"),
        },
    ))
    def post(self, request):
        """
        删除(禁用)域名
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"])
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在！")
        pro_data = ProjectListSerializer(pro_data)
        if not pro_data.data["status"]:
            return JsonResponse(code="999985", msg="该项目已禁用")
        try:
            for j in data["ids"]:
                obj = GlobalHost.objects.get(id=j, project=data["project_id"])
                if obj:
                    name = obj.name
                    # obj.delete()  # 删除
                    obj.status = False
                    obj.save()
                    record_dynamic(project=data["project_id"],
                                   _type="禁用", operationObject="域名", user=request.user.pk, data="禁用域名“%s”" % name)
            return JsonResponse(code="999999", msg="成功！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="host不存在！")
